#pragma once
#ifndef _GLVIEWER_H_
#define _GLVIEWER_H_

#include "TriMesh.h"
#include <QtOpenGL/QGLWidget>
#include <Eigen/Core>

class GLViewer : public QGLWidget
{
	Q_OBJECT

public:
	GLViewer(QWidget *parent = 0);
	~GLViewer();

public slots:
	void setMesh(const CTriMesh& mesh) {
		mesh_ = mesh;
		unifyMesh();
		this->updateGL();
	}

	void setDrawPointsStatus(bool _val) {
		draw_points_ = _val;
		this->updateGL();
	}

	void setDrawTrianglesStatus(bool _val) {
		draw_triangles_ = _val;
		this->updateGL();
	}

	void setDrawEdgesStatus(bool _val) {
		draw_edges_ = _val;
		this->updateGL();
	}

protected:
	void		unifyMesh();
	void		draw();
	void		setMaterial();
	void		setLightAttrib(Eigen::Vector3d pos);
	void		setScene(Eigen::Vector3d ballCenter, float ballRadius);
	void		updateProjectionMatrix();
	void		translate(const Eigen::Vector3d& _trans);
	void		rotate(const Eigen::Vector3d& _axis, float _angle);
	bool		mapToSphere(const Eigen::Vector2i &_point, Eigen::Vector3d &_result);

protected:
	// mouse processing functions
	void		rotation(int _x, int _y);
	void		translation(int _x, int _y);
	void		zoom(float _x);

protected:
	void		mousePressEvent(QMouseEvent *event);
	void		mouseReleaseEvent(QMouseEvent *event);
	void		mouseMoveEvent(QMouseEvent *event);
	void		wheelEvent(QWheelEvent *event);

	void		initializeGL();
	void		resizeGL(int _w, int _h);
	void		paintGL();

private:
	//draw state
	bool			draw_points_;
	bool			draw_edges_;
	bool			draw_triangles_;

	//control
	bool			left_button_down_;
	bool			right_button_down_;
	int			gl_size_width;
	int			gl_size_height;

	// scene position and dimension
	Eigen::Vector3d    ball_center_;
	float			   ball_radius_;

	// projection parameters
	float    near_, far_, fovy_;

	// OpenGL matrices
	double   projection_matrix_[16];
	double	 modelview_matrix_[16];

	// trackball helpers
	Eigen::Vector2i    last_point_2D_;
	Eigen::Vector3d    last_point_3D_;
	bool				   last_point_ok_;

	//light
	Eigen::Vector3d    light_pos_;

	//data
	CTriMesh		mesh_;
};

#endif